#ifndef SKYROAD_TXT_OARCHIVE_H_
#define SKYROAD_TXT_OARCHIVE_H_

#include <string>
#include <vector>
#include <boost/array.hpp>
#include <skyroad/archive/nvp.hpp>
#include <skyroad/detail/config.hpp>
#include <skyroad/util/convert_to.hpp>

class SKYROAD_DECL txt_oarchive
{
public:
    txt_oarchive(std::string& s, int version)
        :m_data(s), m_version(version)
    {
    }


    void write(const std::string& s)
    {
        m_data.append(s);
    }

//     void write(const std::wstring& s)
//     {
//         m_data.append(unicode_to_native(s));
//     }

    void write(unsigned char s) 
    {
        char buf[32];
        m_data.append(itoa(s, buf, 10)); 
    }

    void write(unsigned short s) 
    {
        char buf[32];
        m_data.append(itoa(s, buf, 10));
    }


    void write(unsigned long s)
    {
        char buf[32];
        m_data.append(itoa(s, buf, 10));
    }

    void write(unsigned __int64 s)
    {
        char buf[32];
        m_data.append(_ui64toa(s, buf, 10));
    }

    template <std::size_t N>
    void write(boost::array<char, N>& a) 
    {
        std::string s(&a[0]);
        m_data.append(s);
    }

    template <std::size_t N>
    void write(boost::array<unsigned char, N>& a) 
    {
        std::string s((char*)&a[0],N);
        m_data.append(s);
    }

    template <std::size_t N>
    void write(boost::array<wchar_t, N>& a)
    {
        std::wstring s(&a[0]);
        m_data.append(unicode_to_native(s));
    }

    template <typename T>
    void write(std::vector<T>& v)
    {
        for (int i = 0; i < v.size(); i++)
        {
            serialize(*this, v[i], m_version);
        }
    }

    template <typename Value>
    void write(const nvp<Value>& nv)
    {
 
        if (nv.first != NULL && nv.first[0] != '#')
        {
            m_data.append(nv.first).append("=");
            write(*nv.second);
            m_data.append(" ");
        }
    }

private:
    std::string& m_data; 
    int m_version;
};



template <typename Value>
inline txt_oarchive& operator &(txt_oarchive& out, const nvp<Value>& nv)
{
    out.write(nv);
    return out;
}

template <typename T>
inline txt_oarchive& operator &(txt_oarchive& out, std::vector<T>& v) 
{
    out.write(v);
    return out;
}

#endif